#include "PGPublicLogic.h"
#include "Channels.h"
#include "ChannelManager.h"
#include "Resource.h"
#include "String.h"
#include "SharedPtr.h"
#include "ResourceManager.h"
#include "Database/DatabaseEnv.h"
#include "StringConverter.h"
#include "NGLog.h"
#include "Character.h"
#include "CharManager.h"
#include "Items.h"
#include "ItemManager.h"
#include "WorldPacket.h"
#include "Opcodes.h"
#include "RegionManager.h"
#include "Towns.h"
#include "TownManager.h"
#include "Users.h"
#include "UserManager.h"
#include "Mails.h"
#include "MailManager.h"
#include "WSSocket.h"
#include "WSSocketManager.h"
#include "BSSocket.h"
#include "Missions.h"
#include "MissionManager.h"
#include "Message.h"
#include "MD5.h"
#include "Titles.h"
#include "TitleManager.h"
#include "PGWorldAIInterface.h"
#include "PGPubStruct.h"
#include "Tools.h"
#include "CenterBankManager.h"
#include "VipCardManager.h"
#include "GameDefine.h"
#include ENUM_PATH
#include XMLDATA_MGR_PATH
#include PROTOCOLS_MGR_PATH
#include LOG_MGR_PATH

using namespace AIScript;

//-----------------------------------------------------------------------
CharPtr PublicLogic::CreateCreature(UserPtr & user, bool isCenter)
{
	CharPtr chr;
	if (user.isNull())
		return chr;
	std::list<CharPtr> chars;
	sCharMgr.getCharsList(&chars, 0, 1, "userid = %u", user->getHandle());
	if(!chars.empty())
	{
		chr = chars.front();
		user->setUInt32Field("char_id", chr->getHandle());
		// user->SaveDB();
		return chars.front();
	}
	
	Resource * pChar = sCharMgr.newDumyChar();
	assert(pChar);
	Vector3 pos = sRegionMgr.getWorldRondomPosition();
	pChar->setFloatField("x", pos.x);
	pChar->setFloatField("y", pos.y);
	// pChar->setUInt32Field("id", RandomUInt(0,1) ? RandomUInt(501, 505) : RandomUInt(401, 405));
	// String name = ServerDatabase.EscapeString(user->getStringField("nick"));
	// pChar->setStringField("name", name);
	String name =  user->getStringField("nick");
	int loc = name.find("贵宾", 0);
	if (loc != -1)
		name = GetNickWords();
	pChar->setStringField("name", ServerDatabase.EscapeString(name));
	pChar->setUInt32Field("userid", user->getHandle());
	pChar->setUInt32Field("lv", 1);
	pChar->setUInt32Field("exps", 0);
	pChar->setUInt32Field("status", CharacterStatusFree);
	pChar->setUInt32Field("gz_id", user->getUInt32Field("gz_id"));
	pChar->setUInt32Field("create_time", time(0));
	chr = sCharMgr.loadCharDatabase(pChar);
	sCharMgr.freeDumyChar(pChar);
	CMD5 md5;
	String pwd = md5.GenerateMD5(StringConverter::toString(sXmlDataMgr.GetConfXMLValue("2PWD_DEFAULT")).c_str());
	user->setStringField("passwd2", pwd);
	user->setUInt32Field("char_id", chr->getHandle());
	user->setStringField("nick", name);
	user->SaveDB();
	// 赠送物品
	AddNewPlayerGift(chr, isCenter);
	return chr;	
}
//-----------------------------------------------------------------------
void PublicLogic::AddNewPlayerGift(CharPtr &pChr, const bool isCenter)
{
	if (pChr.isNull())
		return;
	std::map<uint32, uint32> mapGifts = sXmlDataMgr.GetNewPlayerGiftList();
	std::map<uint32, uint32>::iterator iter = mapGifts.begin();
	for (; iter != mapGifts.end(); ++iter)
	{
		if (isCenter)
			CreateItem(pChr, iter->first, 0);
		else
			CreateItem(pChr, iter->first, iter->second);
	}
}
//-----------------------------------------------------------------------
ChannelPtr PublicLogic::CreateNewChannel(ResourceProxy town,const uint32 & march_id)
{
	ChannelPtr pChn;
	if (town.isNull())
		return pChn;
	// 创建新的牌桌
	Resource * pChannel = sChannelMgr.newDumyChannel();
	if(NULL == pChannel)
	{
		sChannelMgr.freeDumyChannel(pChannel);
		return pChn;
	}
	TownPtr pTown = town.getResourcePtr();
	pChannel->setUInt32Field("ai", pTown->getUInt32Field("ai"));
	pChannel->setUInt32Field("town_id", pTown->getHandle());
	Vector3 pos = sRegionMgr.getWorldRondomPosition();
	pChannel->setFloatField("x", pos.x);
	pChannel->setFloatField("y", pos.y);
	pChannel->setFloatField("z", pos.z);
	pChannel->setUInt32Field("type", 1);
	pChannel->setUInt32Field("march_id", march_id);
	pChannel->setUInt32Field("status", en_ChannelStatus_Idle);
	pChannel->setUInt32Field("create_time", time(0));
	pChn = sChannelMgr.loadChannelDatabase(pChannel);
	sChannelMgr.freeDumyChannel(pChannel);
	
	return pChn;
}
//-----------------------------------------------------------------------
uint32 PublicLogic::GetGoldMoney(CharPtr & chr)
{
	if(chr.isNull())
		return 0;
	uint32 userid = chr->getUInt32Field("userid");
	if(userid)
	{
		UserPtr user = sUserMgr.load(userid);
		if(user.isNull())
			return 0;
		return user->getUInt32Field("golds");		
	}
	return 0;
}
//-----------------------------------------------------------------------
void PublicLogic::SetGoldMoney(CharPtr & chr, const uint32 gMoney)
{
	if (chr.isNull())
		return;
	uint32 userid = chr->getUInt32Field("userid");
	if(userid)
	{
		UserPtr user = sUserMgr.getByHandle(userid);
		if (user.isNull()) return;
		user->setUInt32Field("golds", gMoney);	
		user->SaveDB();
		WSSocketPtr socket = chr->getSocket();
		if(!socket.isNull())
		{
			// 通知元宝数据更新
			WorldPacket newP;
			// if(sProtocolsMgr.CreateGoldsUpdatePacket(&newP, gMoney))
				// socket->SendPacket(&newP);
		}
	}
}
//-----------------------------------------------------------------------
ItemPtr PublicLogic::CreateItem(CharPtr & container, const uint32 & model_id, const uint32 & num)
{
	ItemPtr item;
	if(container.isNull())
		return item;
	ItemModelPtr imp = sItemModelMgr.load(model_id);
	if(imp.isNull())
		return item;
	Resource * pItem = sItemMgr.newDumyItem(model_id);
	pItem->setUInt32Field("status", Item::ItemStatusNormal);
	pItem->setUInt32Field("model_id", model_id);
	pItem->setStringField("name", imp->getStringField("name"));
	pItem->setUInt32Field("container", container->getHandle());
	pItem->setUInt32Field("container_type", container->getTargetType());
	// 区分物品类型
	if (imp->getUInt32Field("type") == 2)
	{
		pItem->setUInt32Field("num", imp->getUInt32Field("value") * num);
		pItem->setUInt32Field("value", num);
	}
	else
	{
		pItem->setUInt32Field("num", num);
	}
	
	item = sItemMgr.createItemDatabase(pItem);
	sItemMgr.freeDumyItem(pItem);
	item->load();
	UpdateAboutMoney(container, model_id, num, true);
	WorldPacket newP;
	if(sProtocolsMgr.CreateAddNewItemPacket(&newP, item))
		SendProtocolsToChr(container, &newP);
	return item;
}
//-----------------------------------------------------------------------
void PublicLogic::UpdateAboutMoney(CharPtr &pChr, const uint32 modelId, const uint32 num, bool bSaveDB)
{
	if (pChr.isNull())
		return;
	switch (modelId)
	{
		case ItemModel_Coins: // 铜钱
			{
				pChr->setUInt32Field("coins", num);
				ResourceEvent event;
				event.event_id = en_ResourceEvent_CoinsUpdate;
				event.source = pChr;
				pChr->SendEvent(&event);
				break;
			}
		default:
			return;
	}
	if (bSaveDB)
		pChr->SaveDB();
}
//-----------------------------------------------------------------------
bool PublicLogic::SetItemNum(CharPtr & chr, const uint32 & model_id, const uint32 & num)
{
	ItemPtr item = GetItem(chr, model_id);
	if(item.isNull())
		return false;
	bool bSaveBank = false;
	uint32 myNum = num;
	uint32 maxNumber = sXmlDataMgr.GetConfXMLValue("MAX_COINS");
	if (num > maxNumber)
	{
		myNum = maxNumber;
		uint32 leftNum = num - maxNumber;
		UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
		sBankMgr.SaveWealthInBank(pUser, model_id, leftNum);
		bSaveBank = true;
	}
	item->setUInt32Field("num", myNum);
	item->SaveDB();
	UpdateAboutMoney(chr, model_id, myNum, true);
	// 下发更新物品数量
	 WorldPacket newP;
	if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, model_id, myNum))
		SendProtocolsToChr(chr, &newP);
	// if(sProtocolsMgr.CreateUpdateItemNumberPacketEx(&newP, model_id, num))
	// 	SendProtocolsToChr(chr, &newP);
	// 通知玩家携带现金超出上限，超出部分已存银行
	if (bSaveBank)
	{
		UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
		char msg[256];
		char strOverFlow[] = "overflow";
		sprintf(msg, GetMsgData(strOverFlow, pUser).c_str(), num - maxNumber);
		SendSystemMessage(chr, msg, GetMsgType(strOverFlow, pUser));
	}
	return true;

}
//-----------------------------------------------------------------------
ItemPtr PublicLogic::addItemNum(CharPtr & chr, const uint32 & model_id, const uint32 & addnum, bool bUpdate)
{
	ItemPtr item = GetItem(chr, model_id);
	if(item.isNull())
		return CreateItem(chr, model_id, addnum);
	// 区分物品类型
	uint32 num = 0;
	if (item->model->getUInt32Field("type") == 2)
	{
		num = item->getUInt32Field("num") + item->model->getUInt32Field("value") * addnum;
		item->setUInt32Field("value", item->getUInt32Field("value") + addnum);
	}
	else
	{
		num = item->getUInt32Field("num") + addnum;
	}
	uint32 maxNumber = sXmlDataMgr.GetConfXMLValue("MAX_COINS");
	bool bSaveBank = false;
	uint32 leftNum = 0;
	if (num > maxNumber)
	{
		leftNum = num - maxNumber;
		num = maxNumber;
		UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
		sBankMgr.SaveWealthInBank(pUser, model_id, leftNum);
		bSaveBank = true;
	}
	item->setUInt32Field("num", num);
	item->SaveDB();
	UpdateAboutMoney(chr, model_id, num, true);
	if (bUpdate)
	{
		// 下发更新物品数量
		WorldPacket newP;
		if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, model_id, num))
			SendProtocolsToChr(chr, &newP);
		// if(sProtocolsMgr.CreateUpdateItemNumberPacketEx(&newP, model_id, num))
		// 	SendProtocolsToChr(chr, &newP);
		// 通知玩家携带现金超出上限，超出部分已存银行
		if (bSaveBank)
		{
			UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
			char msg[256];
			char strOverFlow[] = "overflow";
			sprintf(msg, GetMsgData(strOverFlow, pUser).c_str(), leftNum);
			SendSystemMessage(chr, msg, GetMsgType(strOverFlow, pUser));
		}
	}
	return item;
}
//-----------------------------------------------------------------------
bool PublicLogic::reduceItemNum(CharPtr & chr, const uint32 & model_id, const uint32 & rNum, bool bUpdate)
{
	if (chr.isNull())
		return false;
	PGCreatureInterface *pAiChrInfe = TO_CREATURE_INTERFACE(chr->getAIInterface());
	if (NULL == pAiChrInfe)
		return false;
	ItemPtr item = GetItem(chr, model_id);
	if(item.isNull())
		return false;
	uint32 cur_num = item->getUInt32Field("num");
	if(cur_num < rNum)
		return false;
	if(model_id == ItemModel_Coins)
	{
		if(pAiChrInfe->GetFrozenCapital() + rNum > cur_num)
			return false;
	}
	cur_num -= rNum;
	item->setUInt32Field("num", cur_num);
	item->SaveDB();
	UpdateAboutMoney(chr, model_id, cur_num, true);
	if (bUpdate)
	{
		// 下发更新物品数量
		WorldPacket newP;
		if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, model_id, cur_num))
			SendProtocolsToChr(chr, &newP);
		// if(sProtocolsMgr.CreateUpdateItemNumberPacketEx(&newP, model_id, cur_num))
		// 	SendProtocolsToChr(chr, &newP);
		// 检测是否救济
		//pAiChrInfe->CheckCanGetSubsidy();
	}
	return true;
}
//-----------------------------------------------------------------------
ItemPtr PublicLogic::TableAddItemNum(CharPtr & chr, const uint32 & model_id, const uint32 & addnum)
{
	ItemPtr item = GetItem(chr, model_id);
	if(item.isNull())
		return CreateItem(chr, model_id, addnum);
	uint32 num = item->getUInt32Field("num") + addnum;
	uint32 maxNumber = sXmlDataMgr.GetConfXMLValue("MAX_COINS");
	bool bSaveBank = false;
	uint32 leftNum = 0;
	if (num > maxNumber)
	{
		leftNum = num - maxNumber;
		num = maxNumber;
		UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
		sBankMgr.SaveWealthInBank(pUser, model_id, leftNum);
		bSaveBank = true;
	}
	item->setUInt32Field("num", num);
	item->SaveDB();
	UpdateAboutMoney(chr, model_id, num, true);
	// 下发更新物品数量
	WorldPacket newP;
	if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, model_id, num))
		SendProtocolsToChr(chr, &newP);
	// if(sProtocolsMgr.CreateUpdateItemNumberPacketEx(&newP, model_id, num))
	// 	SendProtocolsToChr(chr, &newP);
	// 通知玩家携带现金超出上限，超出部分已存银行
	if (bSaveBank)
	{
		UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
		char msg[256];
		char strOverFlow[] = "overflow";
		sprintf(msg, GetMsgData(strOverFlow, pUser).c_str(), leftNum);
		SendSystemMessage(chr, msg, GetMsgType(strOverFlow, pUser));
	}
	return item;
}
//-----------------------------------------------------------------------
bool PublicLogic::TableReduceItemNum(CharPtr & chr, const uint32 & model_id, const uint32 & rNum)
{
	if (chr.isNull())
		return false;
	PGCreatureInterface *pAiChrInfe = TO_CREATURE_INTERFACE(chr->getAIInterface());
	if (NULL == pAiChrInfe)
		return false;
	ItemPtr item = GetItem(chr, model_id);
	if(item.isNull())
		return false;
	uint32 cur_num = item->getUInt32Field("num");
	if(cur_num < rNum)
		cur_num = 0;
	else
		cur_num -= rNum;
	item->setUInt32Field("num", cur_num);
	item->SaveDB();
	UpdateAboutMoney(chr, model_id, cur_num, true);
	// 下发更新物品数量
	WorldPacket newP;
	if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, model_id, cur_num))
		SendProtocolsToChr(chr, &newP);
	// 检测是否救济
	//pAiChrInfe->CheckCanGetSubsidy();
	return true;
}
//-----------------------------------------------------------------------
ItemPtr PublicLogic::GetItem(CharPtr & chr, const uint32 & model_id)
{
	ItemPtr item;
	std::list<ItemPtr> items;
	chr->getItemsList(&items);
	std::list<ItemPtr>::iterator ii, endii = items.end();
	for(ii = items.begin(); ii != endii; ++ii)
	{
		if((*ii)->getUInt32Field("model_id") == model_id)
		{
			item = *ii;
			return item;
		}
	}
	return item;
}
//-----------------------------------------------------------------------
uint32 PublicLogic::GetItemNum(CharPtr & chr, const uint32 & model_id)
{
	ItemPtr item = GetItem(chr, model_id);
	if(item.isNull())
	{
		return 0;
	}
	return item->getUInt32Field("num");
}
//-----------------------------------------------------------------------
uint64 PublicLogic::GetBankerNum(CharPtr & chr, const uint32 & model_id)
{
	return sBankMgr.GetCenterBankWealth(chr, model_id);
}
//-----------------------------------------------------------------------
uint64 PublicLogic::GetAllNum(CharPtr & chr, const uint32 & model_id)
{
	return GetItemNum(chr, model_id) + GetBankerNum(chr, model_id);
}
//-----------------------------------------------------------------------
void PublicLogic::UpdateItemsInfoInBag(CharPtr & chr)
{
	std::list<ItemPtr> lstItems;
	chr->getItemsList(&lstItems);
	std::list<ItemPtr>::iterator iter = lstItems.begin(), iterEnd = lstItems.end();
	for(; iter !=iterEnd; ++iter)
	{
		(*iter)->ReloadDB();
	}
}
//-----------------------------------------------------------------------
String 	PublicLogic::GetItemName(const uint32 & model_id)
{
	ItemModelPtr model = sItemModelMgr.getByHandle(model_id);
	if(model.isNull())
		return "";
	
	return model->getStringField("name");
}
//-----------------------------------------------------------------------
void 	PublicLogic::CombItemData(CharPtr & pChr)
{
	if(pChr.isNull())
		return ;
	
	// uint32 model_money = 1000, model_match = 1001;
	ItemPtr money,golds;
	std::list<ItemPtr> items;
	pChr->getItemsList(&items);
	std::list<ItemPtr>::iterator ii, endii = items.end();
	for(ii = items.begin(); ii != endii; ++ ii)
	{
		ItemPtr item = (*ii);
		if(item.isNull() || !item->isLoaded())
			continue;
			
		if(item->model->getHandle() == ItemModel_Coins)
		{
			if(money.isNull())
			{
				money = item;
				UpdateAboutMoney(pChr, ItemModel_Coins, item->getUInt32Field("num"), false);
			}
			else
			{
				uint32 tempNum = item->getUInt32Field("num");
				uint32 num = money->getUInt32Field("num");
				item->setUInt32Field("num", 0);
				item->Destroy();				
				money->setUInt32Field("num", num+tempNum);
				UpdateAboutMoney(pChr, ItemModel_Coins, num+tempNum, false);
				// 记录合并日志
				sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_CombItem, ItemModel_Coins, en_UNT_Add, tempNum);
			}
		}
	}
}
//-----------------------------------------------------------------------
void PublicLogic::SendProtocolsToChr(CharPtr & pChr, WorldPacket * packet)
{
	if (pChr.isNull() || NULL == packet)
		return;
	WSSocketPtr socket = pChr->getSocket();
	if(!socket.isNull())
		socket->SendPacket(packet);
}
//-----------------------------------------------------------------------
bool PublicLogic::SendSystemMessage(CharPtr & chr, const char* pStr, const uint8 & type)
{
	WSSocketPtr socket = chr->getSocket();
	if(socket.isNull())
		return false;
	WorldPacket newP;
	if(sProtocolsMgr.CreateLocalMessagePacket(&newP, pStr, type))
		socket->SendPacket(&newP);
	return true;
}

//-----------------------------------------------------------------------
EffectPtr PublicLogic::AddEffect(ResourceProxy owner, 
									const uint32 & model_id, 
									const uint32 & begin_time,
									const uint32 & data1 /* = 0 */, 
									const uint32 & data2 /* = 0 */, 
									const uint32 & data3 /* = 0 */, 
									const uint32 & data4 /* = 0 */,
									const float & fdata1 /* = 0.0f */,
									const float & fdata2 /* = 0.0f */)
{
	EffectPtr effectPtr;
	if(owner.isNull() || !model_id)
		return effectPtr;
	
	if(owner._type == ResourceTypeItem)
	{
		ItemPtr item = owner.getResourcePtr();
		if(item.isNull())
			return effectPtr;
		
		std::list<EffectPtr> effects;
		item->getEffectsList(&effects);
		std::list<EffectPtr>::iterator ei = effects.begin(), endei = effects.end();
		while(ei != endei)
		{
			if((*ei)->model->getHandle() == model_id)
				return *ei;			
				
			++ ei;
		}
	}
	else if(owner._type == ResourceTypeCharacter)
	{
		CharPtr chr = owner.getResourcePtr();
		if(chr.isNull())
			return effectPtr;
	}
	
	ResourcePtr modelPtr = sEffectModelMgr.load(model_id);
	if(modelPtr.isNull())
		return effectPtr;
	// assert(!modelPtr.isNull());

	Resource * pEffect =  sEffectMgr.newDumyEffect();
	assert(pEffect);
	
	pEffect->setUInt32Field("effect_model_id", model_id);
	pEffect->setUInt32Field("status", Effect::EffectStatusProcess);
	pEffect->setUInt32Field("owner_type", owner.getTargetType());
	pEffect->setUInt32Field("owner_id", owner._handle);
	
	pEffect->setInt32Field("data1", (int32)data1);
	pEffect->setInt32Field("data2", (int32)data2);
	pEffect->setInt32Field("data3", (int32)data3);
	pEffect->setInt32Field("data4", (int32)data4);
	
	pEffect->setFloatField("fdata1", fdata1);
	pEffect->setFloatField("fdata2", fdata2);
	
	pEffect->setUInt32Field("start_time", begin_time);	
	uint32 duration = uint32(modelPtr->getUInt32Field("duration_time") / 1000);
	
	if(duration)
		pEffect->setUInt32Field("end_time", begin_time + duration);
		
	effectPtr = sEffectMgr.createEffectDatabase(pEffect);
	if(!effectPtr.isNull())
		effectPtr->load();
	
	sEffectMgr.freeDumyEffect(pEffect);
	
	return effectPtr;
}

//-----------------------------------------------------------------------
EffectPtr PublicLogic::GetEffect(ResourceProxy owner, const uint32 & model_id)
{
	EffectPtr effect;
	if(owner._type == ResourceTypeCharacter)
	{
		CharPtr chr = owner.getResourcePtr();
		if(!chr.isNull())
		{
			std::list<EffectPtr> effects;
			chr->getEffectsList(&effects);
			std::list<EffectPtr>::iterator ii, endii = effects.end();
			for(ii = effects.begin(); ii != endii; ++ ii)
			{
				if((*ii)->model->getHandle() == model_id)
					return *ii;
			}
		}
	}
	
	return effect;
}
//----------------------------------------------------
void PublicLogic::Broadcast(WorldPacket &packet, std::vector<CharPtr> &vecChars, const uint32 exceptId)
{
	std::vector<CharPtr>::iterator iter = vecChars.begin(), iterEnd = vecChars.end();
	for (; iter != iterEnd; ++iter)
	{
		if (exceptId == (*iter)->getHandle())
			continue;
		WSSocketPtr socket = (*iter)->getSocket();
		if (!socket.isNull())
			socket->SendPacket(&packet);
	}
}
//-----------------------------------------------------------------------
bool PublicLogic::FilterChars(String str, String &outStr)
{
	if (str.length() <= 10)
	{
		outStr = str;
		return true;
	}
	outStr = "";
	size_t pos = 0;
	int count = 0;
	bool last_ch = false;
	while( pos < str.size())
	{
		if(last_ch)
		{
			if(count >=10)
			{
				outStr += "*";
				break;
			}
		}
		else
		{
			if(count >=9)
			{
				outStr += "*";
				break;
			}
		}
		String subStr = str.substr(pos,3);
		if(StringUtil::checkStringUTF8(subStr))
		{
			outStr += subStr;
			count += 2;
			pos += 3;
			last_ch = true;
		}
		else
		{
			outStr += str[pos];
			count += 1;
			pos += 1;
			last_ch = false;
		}
		
	}
	return true;
}

//-----------------------------------------------------------------------
/**
 * 清理DDZ游戏邮件：清理超过限制日期的已读邮件
 */
bool PublicLogic::CleanAllMails()
{
	uint32 limitDays = sXmlDataMgr.GetConfXMLValue("MAIL_LIMITDAYS");
	return CharacterDatabase.WaitExecute("update `game_mails` set `status` = %u where `status` = %u and DATEDIFF(now(),"
									"FROM_UNIXTIME(`create_time`)) > %u;",
									Mail::MailStatusDeleted, Mail::MailStatusOpen, limitDays);
}
//-----------------------------------------------------------------------
/**
 * 清理个人邮箱，如果数量小于规定最大数量，不用清理，直接返回；否则，清理超过限制日期的已读邮件；如果没有可供清理的已读邮件，则清理时间最早的若干邮件
 */
bool PublicLogic::CleanUserMails(const uint32 userId)
{
	// 个人邮件最大数量
	uint32 maxNumber = sXmlDataMgr.GetConfXMLValue("MAIL_MAXNUM");
	uint32 mailNum = sMailMgr.getDBCount("`recv_serial` = %u", userId);
	if (mailNum < maxNumber)
		return true;
	std::list<MailPtr> lstMails;
	// 已读邮件清理限制日期
	uint32 limitDays = sXmlDataMgr.GetConfXMLValue("MAIL_LIMITDAYS");
	if (!sMailMgr.getMailList(&lstMails, 0, mailNum, "`recv_serial` = %u and `status` = %u and DATEDIFF(now(),FROM_UNIXTIME(`create_time`)) > %u", 
		userId, Mail::MailStatusOpen, limitDays))
		return false;
	if (lstMails.size() > 0)
	{
		std::list<MailPtr>::iterator iter(lstMails.begin());
		for (; iter != lstMails.end(); ++iter)
		{
			(*iter)->setUInt32Field("status", Mail::MailStatusDeleted);
			(*iter)->SaveDB();
		}
	}
	else
	{
		// 个人邮件限制数量
		uint32 limitNumber = sXmlDataMgr.GetConfXMLValue("MAIL_LIMITNUM"); 
		lstMails.clear();
		if (!sMailMgr.getMailList(&lstMails, limitNumber, mailNum, "`recv_serial` = %u order by `create_time` desc", userId))
			return false;
		std::list<MailPtr>::iterator iter(lstMails.begin());
		for (; iter != lstMails.end(); ++iter)
		{
			(*iter)->setUInt32Field("status", Mail::MailStatusDeleted);
			(*iter)->SaveDB();
		}
	}
	return true;
}
//-----------------------------------------------------------------------
void PublicLogic::Pwd2LockedMessage(UserPtr &pUser, const uint32 leftTime)
{
	if (pUser.isNull())
		return;
	WSSocketPtr socket = pUser->m_Socket.getResourcePtr();
	if (socket.isNull())
		return;
	char buf[256];
	memset(buf, 0, sizeof(buf));
	
	char strPwd2locked[] = "pwd2locked";
	sprintf(buf, GetMsgData(strPwd2locked, pUser).c_str(), leftTime);
	WorldPacket packet;
	if (sProtocolsMgr.CreateLocalMessagePacket(&packet, buf, GetMsgType(strPwd2locked, pUser)))
		socket->SendPacket(&packet);
}
//-----------------------------------------------------------------------
void PublicLogic::LoginWellcomeMessage(UserPtr &pUser)
{
	if (pUser.isNull())
		return;
	WSSocketPtr socket = pUser->m_Socket.getResourcePtr();
	if (socket.isNull())
		return;
	WorldPacket packet;
	char buf[256];
	memset(buf, 0, sizeof(buf));
	uint32 lastTime = pUser->getUInt32Field("ll_time");
	if (!sTools.IsSameDate(lastTime))
	{
		String pMsgName = "";
		time_t ti = time(0);
		tm *ttm = localtime(&ti);
		switch (ttm->tm_wday)
		{
			case 0:
				pMsgName = "login_sunday";
				break;
			case 1:
				pMsgName = "login_monday";
				break;
			case 2:
				pMsgName = "login_tuesday";
				break;
			case 3:
				pMsgName = "login_wednesday";
				break;
			case 4:
				pMsgName = "login_thursday";
				break;
			case 5:
				pMsgName = "login_friday";
				break;
			case 6:
				pMsgName = "login_saturday";
				break;
			default:
				return;
		}
		
		char strMsgName[256];
		sprintf(strMsgName, "%s", pMsgName.c_str());
		
		sprintf(buf, GetMsgData(strMsgName, pUser).c_str(), ttm->tm_mon + 1, ttm->tm_mday);
		if (sProtocolsMgr.CreateLocalMessagePacket(&packet, buf, GetMsgType(strMsgName, pUser)))
			socket->SendPacket(&packet);
	}
	memset(buf, 0, sizeof(buf));
	char strLoginWel[] = "loginwellcome";
	sprintf(buf, GetMsgData(strLoginWel, pUser).c_str(), sTools.GetCurDateTime(lastTime).c_str());
	if (sProtocolsMgr.CreateLocalMessagePacket(&packet, buf, GetMsgType(strLoginWel, pUser)))
		socket->SendPacket(&packet);
}
//-----------------------------------------------------------------------
uint8 PublicLogic::CkExchageTicket(CharPtr &pChr, String &ticket)
{
	if (pChr.isNull())
		return 0;
	String strMsg;
	GameExchange gexc;
	// 兑换卡是否存在
	if (!sItemMgr.getExchangeDB(ticket, &gexc)) 
		return en_ExchangeResult_TicketNotExisited;
	// 兑换卡是否过期
	if (sTools.GetDateTimeSeconds(gexc.end_time) < time(0))
		return en_ExchangeResult_TicketOverdue;
	// 兑换卡是否已经被兑换过
	if (gexc.status == 2) 
		return en_ExchangeResult_TicketExchanged;
	if (gexc.item_model1 > 0)
	{
		sPubLogic.addItemNum(pChr, gexc.item_model1, gexc.item_num1);
		strMsg += StringConverter::toString(gexc.item_num1);
		strMsg += "x";
		strMsg += gexc.item_name1;
		strMsg += " ";
		// 记录日志
		sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_Exchange, gexc.item_model1, en_UNT_Add, gexc.item_num1, gexc.exchange_id);
	}
	if (gexc.item_model2 > 0)
	{
		sPubLogic.addItemNum(pChr, gexc.item_model2, gexc.item_num2);
		strMsg += StringConverter::toString(gexc.item_num2);
		strMsg += "x";
		strMsg += gexc.item_name2;
		strMsg += " ";
		// 记录日志
		sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_Exchange, gexc.item_model2, en_UNT_Add, gexc.item_num2, gexc.exchange_id);
	}
	if (gexc.item_model3 > 0)
	{
		sPubLogic.addItemNum(pChr, gexc.item_model3, gexc.item_num3);
		strMsg += StringConverter::toString(gexc.item_num3);
		strMsg += "x";
		strMsg += gexc.item_name3;
		strMsg += " ";
		// 记录日志
		sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_Exchange, gexc.item_model3, en_UNT_Add, gexc.item_num3, gexc.exchange_id);
	}
	if (gexc.item_model4 > 0)
	{
		sPubLogic.addItemNum(pChr, gexc.item_model4, gexc.item_num4);
		strMsg += StringConverter::toString(gexc.item_num4);
		strMsg += "x";
		strMsg += gexc.item_name4;
		// 记录日志
		sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_Exchange, gexc.item_model4, en_UNT_Add, gexc.item_num4, gexc.exchange_id);
	}
	// 发送系统消息
	WSSocketPtr socket = pChr->getSocket();
	if (!socket.isNull())
	{
		UserPtr pUser = socket->getCurrentUser();
		char strChangeSucess[] = "changesucceed";
		WorldPacket packet;
		if (sProtocolsMgr.CreateLocalMessagePacket(&packet, GetMsgData(strChangeSucess, pUser) + strMsg, GetMsgType(strChangeSucess, pUser)))
			socket->SendPacket(&packet);
	}
	// 更新兑换相关数据
	gexc.status = 2;
	gexc.token_user = pChr->getUInt32Field("userid");
	gexc.token_time = sTools.GetCurDateTime();
	sItemMgr.updateExchangeDB(&gexc);
	return en_ExchangeResult_Success;
}
//-----------------------------------------------------------------------
void PublicLogic::WholeServerBroadcast(WorldPacket *pPacket, const uint32 gzId)
{
	if (NULL == pPacket)
		return;
	std::list<ResourcePtr> sock_list;
	sWSSocketMgr.getSocketList(sock_list);
	if(sock_list.empty())
		return;
	std::list<ResourcePtr>::iterator iter,ei = sock_list.end();
	for(iter = sock_list.begin(); iter != ei; ++iter)
	{
		WSSocketPtr socket = (*iter);
		if(socket.isNull() || socket->m_Char.isNull())
			continue;
		CharPtr pChr = socket->getCurrentCharacter();
		if (pChr.isNull())
			continue;
		if (gzId > 0)
		{
			if (pChr->getUInt32Field("gz_id") != gzId)
				continue;
		}
		socket->SendPacket(pPacket);
	}
}
//-----------------------------------------------------------------------
void PublicLogic::WholeBroadcastByPlateId(WorldPacket *pPacket, const uint32 fromId)
{
	if (NULL == pPacket)
		return;
	std::list<ResourcePtr> sock_list;
	sWSSocketMgr.getSocketList(sock_list);
	if(sock_list.empty())
		return;
	std::list<ResourcePtr>::iterator iter,ei = sock_list.end();
	for(iter = sock_list.begin(); iter != ei; ++iter)
	{
		WSSocketPtr socket = (*iter);
		if(socket.isNull() || socket->m_Char.isNull())
			continue;
		CharPtr pChr = socket->getCurrentCharacter();
		if (pChr.isNull())
			continue;
		UserPtr pUser = socket->getCurrentUser();
		if(pUser.isNull())
			continue;
		if (fromId > 0)
		{
			// 不是一个分区或不是银商，跳过
			if (pUser->getUInt32Field("reg_from") != fromId && !IS_CREATURE_FLAG(pChr, en_CreatureFlag_BothMCount))
				continue;
		}
		socket->SendPacket(pPacket);
	}
}
//-----------------------------------------------------------------------
void PublicLogic::HallBroadcast(WorldPacket * pPacket)
{
	if (NULL == pPacket)
		return;
	std::list<ResourcePtr> sock_list;
	sWSSocketMgr.getSocketList(sock_list);
	if(sock_list.empty())
		return;
	std::list<ResourcePtr>::iterator iter,ei = sock_list.end();
	for(iter = sock_list.begin(); iter != ei; ++iter)
	{
		WSSocketPtr socket = (*iter);
		if(socket.isNull() || socket->m_Char.isNull())
			continue;
		CharPtr pChr = socket->getCurrentCharacter();
		if (pChr.isNull())
			continue;
		PGCreatureInterface * pAWCI = TO_CREATURE_INTERFACE(pChr->getAIInterface());
		if(pAWCI && 0 == pAWCI->GetTownId())
			socket->SendPacket(pPacket);
	}
}
//-----------------------------------------------------------------------
void PublicLogic::BroadcastEx(WorldPacket * pPacket)
{
	if (NULL == pPacket)
		return;
	std::list<ResourcePtr> sock_list;
	sWSSocketMgr.getSocketList(sock_list);
	if(sock_list.empty())
		return;
	std::list<ResourcePtr>::iterator iter,ei = sock_list.end();
	for(iter = sock_list.begin(); iter != ei; ++iter)
	{
		WSSocketPtr socket = (*iter);
		if(socket.isNull() || socket->m_Char.isNull())
			continue;
		socket->SendPacket(pPacket);
	}
}
//-----------------------------------------------------------------------
void PublicLogic::SendNotice(String &strMsg, const uint32 type, const uint32 gzId)
{
	WorldPacket packet;
	if(sProtocolsMgr.CreateLocalMessagePacket(&packet, strMsg, type))
		WholeServerBroadcast(&packet, gzId);
}
//-----------------------------------------------------------------------
void PublicLogic::SendMsgToPlayer(const uint32 userId, String &strMsg, const uint32 type)
{
	WorldPacket packet;
	if(sProtocolsMgr.CreateLocalMessagePacket(&packet, strMsg, type))
	{
		UserPtr pUser = sUserMgr.getByHandle(userId);
		if (pUser.isNull())
			return;
		WSSocketPtr socket = pUser->m_Socket.getResourcePtr();
		if (socket.isNull())
			return;
		socket->SendPacket(&packet);
	}
}
//-----------------------------------------------------------------------
String PublicLogic::RvRpDBCharacter(String &str, bool bRemove)
{
	String ret = str;
	String::size_type pos;
	if (bRemove)
	{
		while((pos = ret.find('\'')) != String::npos)
		{
			ret.erase(pos,1);
		}
		while((pos = ret.find('\\')) != String::npos)
		{
			ret.erase(pos,1);
		}
		while((pos = ret.find(';')) != String::npos)
		{
			ret.erase(pos,1);
		}
		while((pos = ret.find(' ')) != String::npos)
		{
			ret.erase(pos,1);
		}
	}
	else
	{
		while((pos = ret.find('\'')) != String::npos)
		{
			ret.replace(pos, 1, 1, '.');
		}
		while((pos = ret.find('\\')) != String::npos)
		{
			ret.replace(pos, 1, 1, '.');
		}
		while((pos = ret.find(';')) != String::npos)
		{
			ret.replace(pos, 1, 1, '.');
		}
		while((pos = ret.find(' ')) != String::npos)
		{
			ret.replace(pos, 1, 1, '.');
		}
		while((pos = ret.find(' ')) != String::npos)
		{
			ret.replace(pos, 1, 1, '.');
		}
	}
	return ret;
}
//-----------------------------------------------------------------------
bool PublicLogic::AddCreatureTitle(CharPtr & pChr, EffectPtr & pEffect)
{
	if(pChr.isNull() || pEffect.isNull())
		return false;
	PGCreatureInterface * pAWCI = TO_CREATURE_INTERFACE(pChr->getAIInterface());
	if(!pAWCI)	
		return false;
	// 下发产生新成就
	WorldPacket packet;
	if (sProtocolsMgr.CreateGetNewEffortPacket(&packet, pEffect->model->getHandle()))
		SendProtocolsToChr(pChr, &packet);
	// // 消息
	// char msg[256];
	// sprintf(msg, sMsg.getMessage("new_effort").c_str(), pEffect->model->getStringField("name").c_str());
	// SendSystemMessage(pChr, msg, sMsg.getType("new_effort"));
	pAWCI->AddNewTitle(pEffect->model->getHandle());
	ResourceProxy proxy = (ResourcePtr)pEffect;
	sResourceControlMgr.destroyResource(proxy);
	return true;
}
//-----------------------------------------------------------------------
bool PublicLogic::CountEffectNumber(EffectPtr &pEffect, CharPtr &pChr)
{
	if(pChr.isNull() || pEffect.isNull())
		return false;
	uint32 count = pEffect->getUInt32Field("data1");
	if (++count < pEffect->model->getUInt32Field("effect1"))
	{
		pEffect->setUInt32Field("data1", count);
		pEffect->SaveDB();
		return true;
	}
	else if (count == pEffect->model->getUInt32Field("effect1"))
	{
		pEffect->setUInt32Field("data1", count);
		AddCreatureTitle(pChr, pEffect);
		// 更新成就数量
		pChr->setUInt32Field("ability", pChr->getUInt32Field("ability") + 1);
		// 获得成就
		ResourceEvent event;
		event.event_id = en_ResourceEvent_GetEffort;
		event.source = pChr;
		pChr->SendEvent(&event);
	}
	return false;
}
//-----------------------------------------------------------------------
bool PublicLogic::CheckOverLimitPerDay(CharPtr &pChr, const bool bSendMsg)
{
	if (!pChr.isNull())
	{
		uint32 limit = sXmlDataMgr.GetConfXMLValue("LW_MAXCOIN");
		int32 curCoins = pChr->getInt32Field("marriage");
		if (limit > 0 && abs(curCoins) >= (int32)limit)
		{
			if (bSendMsg)
			{
				// 下发提醒
				WorldPacket packet;
				if (sProtocolsMgr.CreateTellToDoPacket(&packet, en_RemindType_DayLimit, curCoins, limit))
					SendProtocolsToChr(pChr, &packet);
				UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
				// 消息
				char msg[256];
				char strOverLimit[] = "over_limit";
				sprintf(msg, GetMsgData(strOverLimit, pUser).c_str(), limit);
				SendSystemMessage(pChr, msg, GetMsgType(strOverLimit, pUser));
			}
			return true;
		}
	}
	return false;
}
//-----------------------------------------------------------------------
// ItemPtr PublicLogic::AddMammonCard(CharPtr & chr, const uint32 modelId, const uint32 addnum)
// {
	// ItemPtr item = GetItem(chr, modelId);
	// if(item.isNull())
		// return CreateItem(chr, modelId, addnum);
	// uint32 num = item->getUInt32Field("num");
	// // if (!sTools.IsSameYear(item->getUInt32Field("handle_time")))
	// // {
		// // num = 0;
		// // item->setUInt32Field("handle_time", time(0));
	// // }
	// num += addnum;
	// item->setUInt32Field("num", num);
	// item->SaveDB();
	// // 下发更新物品数量
	// WorldPacket newP;
	// if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, modelId, num))
		// SendProtocolsToChr(chr, &newP);
	// return item;
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::ReduceMammonCard(CharPtr & chr, const uint32 rNum, uint32 &coins)
// {
	// if (chr.isNull())
		// return false;
	// list<ItemPtr> lstItems;
	// chr->getItemsList(&lstItems);
	// ItemPtr item;
	// uint32 multiple = 0;
	// // 获取背包物品信息
	// list<ItemPtr>::iterator iter = lstItems.begin(), iterEnd = lstItems.end();
	// for(; iter !=iterEnd; ++iter)
	// {
		// if((*iter)->getItemStatus() == Item::ItemStatusDeleted)
			// continue;
		// ItemModelPtr & model = (*iter)->model;
		// if(model.isNull())
			// continue;
		// if (model->getUInt32Field("type") == 1 && model->getUInt32Field("sub_type") == 1)
		// {
			// if ((*iter)->getUInt32Field("num") > 0 && model->getUInt32Field("maxhp") > multiple)
			// {
				// multiple = model->getUInt32Field("maxhp"); // 倍数
				// item = *iter;
			// }
		// }
	// }
	// if(item.isNull())
		// return false;
	// uint32 cur_num = item->getUInt32Field("num");
	// // if (!sTools.IsSameYear(item->getUInt32Field("handle_time")))
	// // {
		// // cur_num = 0;
	// // }
	// if(cur_num < rNum)
		// return false;
	// coins = uint32(coins * (1 + multiple * 0.01f));
	// cur_num -= rNum;
	// item->setUInt32Field("num", cur_num);
	// item->SaveDB();
	// // 下发更新物品数量
	// WorldPacket newP;
	// if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, item->model->getHandle(), cur_num))
		// SendProtocolsToChr(chr, &newP);
	// sLogDataMgr.UpdateItemsInfoLog(chr, en_ST_Gateway, item->model->getHandle(), en_UNT_Reduce, rNum);
	// return true;
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::UpdateMammonCard(CharPtr & chr)
// {
	// if (chr.isNull())
		// return false;
	// list<ItemPtr> lstItems;
	// chr->getItemsList(&lstItems);
	// // 获取背包物品信息
	// list<ItemPtr>::iterator iter = lstItems.begin(), iterEnd = lstItems.end();
	// for(; iter !=iterEnd; ++iter)
	// {
		// ItemPtr item = *iter;
		// if(item->getItemStatus() == Item::ItemStatusDeleted)
			// continue;
		// ItemModelPtr & model = item->model;
		// if(model.isNull())
			// continue;
		// if (model->getUInt32Field("type") == 1 && model->getUInt32Field("sub_type") == 1) // 找到财神卡
		// {
			// if (sTools.IsSameYear(item->getUInt32Field("handle_time") || item->getUInt32Field("num") == 0))
			// {
				// continue;
			// }
			// uint32 cur_num = 0;
			// item->setUInt32Field("num", cur_num);
			// item->setUInt32Field("handle_time", time(0));
			// item->SaveDB();
			// // 下发更新物品数量
			// WorldPacket newP;
			// if(sProtocolsMgr.CreateUpdateItemNumberPacket(&newP, item->model->getHandle(), cur_num))
				// SendProtocolsToChr(chr, &newP);
		// }
	// }
	// return true;
// }
// //-----------------------------------------------------------------------
// void PublicLogic::MammonCome(CharPtr & chr, bool bPresend)
// {
	// if (chr.isNull() || chr->getUInt32Field("lv") < sXmlDataMgr.GetConfXMLValue("NEED_LV"))
		// return;
	// // 子游戏不送
	// UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
	// if (pUser.isNull() || (bool)pUser->getUInt32Field("flag"))
		// return;
	// bool bCanSend = true;
	// if (bPresend)
	// {
		// bCanSend = chr->getUInt32Field("lv") == sXmlDataMgr.GetConfXMLValue("NEED_LV");
	// }
	// else
	// {
		// list<ItemPtr> lstItems;
		// chr->getItemsList(&lstItems);
		// // 获取背包物品信息
		// list<ItemPtr>::iterator iter = lstItems.begin(), iterEnd = lstItems.end();
		// for(; iter !=iterEnd; ++iter)
		// {
			// ItemPtr item = *iter;
			// if(item->getItemStatus() == Item::ItemStatusDeleted)
				// continue;
			// ItemModelPtr & model = item->model;
			// if(model.isNull())
				// continue;
			// if (model->getUInt32Field("type") == 1 && model->getUInt32Field("sub_type") == 1) // 找到财神卡
			// {
				// bCanSend = false;
				// break;
			// }
		// }
	// }
	// if (bCanSend)
	// {
		// AddMammonCard(chr, ItemModel_Mammon, 1);
	// }
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::BeHadMammonCard(CharPtr & chr)
// {
	// if (chr.isNull())
		// return false;
	// list<ItemPtr> lstItems;
	// chr->getItemsList(&lstItems);
	// // 获取背包物品信息
	// list<ItemPtr>::iterator iter = lstItems.begin(), iterEnd = lstItems.end();
	// for(; iter !=iterEnd; ++iter)
	// {
		// ItemPtr item = *iter;
		// if(item->getItemStatus() == Item::ItemStatusDeleted)
			// continue;
		// ItemModelPtr & model = item->model;
		// if(model.isNull())
			// continue;
		// if (model->getUInt32Field("type") == 1 && model->getUInt32Field("sub_type") == 1 && item->getUInt32Field("num") > 0) // 找到财神卡
		// {
			// return true;
		// }
	// }
	// return false;
// }
// //-----------------------------------------------------------------------
// void PublicLogic::TouchLuckyCard(CharPtr & chr, int32 winCoins)
// {
	// if (chr.isNull() || winCoins <= 0)
		// return;
	// ItemPtr pItem;
	// GetLuckCard(chr, pItem);
	// if (pItem.isNull())
		// return;
	// uint32 maxPoint = pItem->model->getUInt32Field("maxhp"); // 单次上限点数
	// uint32 leftPoint = pItem->getUInt32Field("num"); // 当前剩余点数
	// uint32 realPoint = leftPoint > maxPoint ? maxPoint : leftPoint;	// 真实可用点数
	// if ((uint32)winCoins < realPoint)
	// {
		// realPoint = winCoins;
	// }
	// pItem->setUInt32Field("num", leftPoint - realPoint);
	// pItem->SaveDB();
	// uint32 purview = pItem->model->getUInt32Field("max_num"); // 总权重
	// uint32 curPurView = RandomUInt(0, purview-1);
	// float multiple = 0.0f;
	// uint32 tempPur = uint32(pItem->model->getFloatField("range_x2") * purview);
	// bool bNotice = false;
	// if (curPurView < tempPur)
	// {
		// multiple = pItem->model->getFloatField("range_x1");
		// bNotice = pItem->model->getFloatField("offset_x") > 0;
	// }
	// else 
	// {
		// tempPur += uint32(pItem->model->getFloatField("range_y2") * purview);
		// if (curPurView < tempPur)
		// {
			// multiple = pItem->model->getFloatField("range_y1");
			// bNotice = pItem->model->getFloatField("offset_y") > 0;
		// }
		// else
		// {
			// multiple = pItem->model->getFloatField("range_z1");
			// bNotice = pItem->model->getFloatField("offset_z") > 0;
		// }
	// }
	// uint32 addCoins = uint32(realPoint * multiple);
	// UserPtr pUser = sUserMgr.getByHandle(chr->getUInt32Field("userid"));
	// char msg[256];
	// if (bNotice)
	// {
		// sprintf(msg, GetMsgData("lucky_notice", pUser).c_str(), chr->getStringField("name2").c_str(), realPoint, multiple, addCoins);
		// String strMsg(msg);
		// SendNotice(strMsg, GetMsgType("lucky_notice", pUser));
	// }
	// // 通知玩家得到额外奖励
	// uint32 modelId = pItem->model->getHandle();
	// WorldPacket packet;
	// if(sProtocolsMgr.CreateUsedLuckyCardPacket(&packet, modelId, realPoint, multiple, addCoins))
		// SendProtocolsToChr(chr, &packet);
	// // 消息提示
	// memset(msg, 0, sizeof(msg));
	// sprintf(msg, GetMsgData("lucky_card", pUser).c_str(), realPoint, addCoins);
	// SendSystemMessage(chr, msg, GetMsgType("lucky_card", pUser));
	// // 更新幸运点数
	// if(sProtocolsMgr.CreateUpdateItemNumberPacket(&packet, pItem->model->getHandle(), pItem->getUInt32Field("num")))
	// {
		// SendProtocolsToChr(chr, &packet);
	// }
	// // 添加额外的钱
	// addItemNum(chr, ItemModel_Coins, addCoins);
	// // 记录幸运卡增加铜钱日志
	// sLogDataMgr.UpdateItemsInfoLog(chr, en_ST_Item, ItemModel_Coins, en_UNT_Add, addCoins, modelId, realPoint, uint32(multiple));
	// // 记录扣除幸运卡点数日志
	// sLogDataMgr.UpdateItemsInfoLog(chr, en_ST_Item, modelId, en_UNT_Reduce, realPoint, modelId);
	// // 幸运点经验
	// AddLuckyCardExps(chr, modelId, realPoint);
	
	// if(sProtocolsMgr.CreateCharSpecificPacket(&packet,chr->getHandle(),en_CharSpecific_LuckyStar,uint32(multiple),addCoins))
	// {
		// PGCreatureInterface * pChrInter = TO_CREATURE_INTERFACE(chr->getAIInterface());
		// if(pChrInter == NULL)
			// return ;
		
		// uint32 chnId = pChrInter->GetChannelId();
		// if (chnId == 0)
			// return;
		// ChannelPtr pChannel = sChannelMgr.getByHandle(chnId); 
		// if(pChannel.isNull())
			// return ;
		
		// WAIChannelInterface *pAiChanInfe = TO_CHANNEL_INTERFACE(pChannel->getAIInterface());
		// if (pAiChanInfe == NULL)
			// return;
		
		// pAiChanInfe->Broadcast(&packet, 0, false);
	// }
// }
// //-----------------------------------------------------------------------
// void PublicLogic::GetLuckCard(CharPtr & chr, ItemPtr & luckCard)
// {
	// if (chr.isNull())
		// return;
	// list<ItemPtr> lstItems;
	// chr->getItemsList(&lstItems);
	// // 获取背包物品信息
	// list<ItemPtr>::iterator iter = lstItems.begin(), iterEnd = lstItems.end();
	// for(; iter !=iterEnd; ++iter)
	// {
		// ItemPtr item = *iter;
		// if(item->getItemStatus() == Item::ItemStatusDeleted)
			// continue;
		// ItemModelPtr & model = item->model;
		// if(model.isNull())
			// continue;
		// if (model->getUInt32Field("type") == 2 && model->getUInt32Field("sub_type") == 1 && item->getUInt32Field("num") > 0) // 找到幸运卡
		// {
			// if (luckCard.isNull() || luckCard->model->getHandle() < model->getHandle())
			// {
				// luckCard = item;
			// }
		// }
	// }
// }
// //-----------------------------------------------------------------------
// void PublicLogic::GetLuckCardList(CharPtr & chr, std::list<ItemPtr> &lstLucks)
// {
	// if (chr.isNull())
		// return;
	// list<ItemPtr> lstItems;
	// chr->getItemsList(&lstItems);
	// // 获取背包物品信息
	// list<ItemPtr>::iterator iter = lstItems.begin(), iterEnd = lstItems.end();
	// for(; iter !=iterEnd; ++iter)
	// {
		// ItemPtr item = *iter;
		// if(item->getItemStatus() == Item::ItemStatusDeleted)
			// continue;
		// ItemModelPtr & model = item->model;
		// if(model.isNull())
			// continue;
		// if (model->getUInt32Field("type") == 2 && model->getUInt32Field("sub_type") == 1 && item->getUInt32Field("num") > 0) // 找到幸运卡
		// {
			// lstLucks.push_back(item);
		// }
	// }
// }
// //-----------------------------------------------------------------------
// void PublicLogic::PacketPlayerSameInfo(WorldPacket * pPacket, CharPtr & pChr)
// {
	// if (pChr.isNull() || pPacket == NULL)
		// return;
	// if (pChr->isNPC())
	// {
		// AppendPacketString<uint8>(pPacket, ""); // ip真实地址
	// }
	// else
	// {
		// UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid")); 
		// if (pUser.isNull())
			// return;
		// AppendPacketString<uint8>(pPacket, pUser->getStringField("addr")); // ip真实地址
	// }
// }
// //-----------------------------------------------------------------------
// String PublicLogic::GetMsgData(char* key, UserPtr &pUser)
// {
	// if (pUser.isNull())
	// {
		// return "";
	// }
	// String strKey(key);
	// switch (pUser->getUInt32Field("gz_id"))
	// {
		// case en_Language_Chinese:
			// strKey += "_zh";
			// break;
		// case en_Language_English:
			// strKey += "_en";
			// break;
		// default:
			// strKey += "_zh";
			// break;
	// }
	// return sMsg.getMessage(strKey);
// }
// //-----------------------------------------------------------------------
// uint32 PublicLogic::GetMsgType(char* key, UserPtr &pUser)
// {
	// if (pUser.isNull())
	// {
		// return 0;
	// }
	// String strKey(key);
	// switch (pUser->getUInt32Field("gz_id"))
	// {
		// case en_Language_Chinese:
			// strKey += "_zh";
			// break;
		// case en_Language_English:
			// strKey += "_en";
			// break;
		// default:
			// strKey += "_zh";
			// break;
	// }
	// return sMsg.getType(strKey);
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::NewPlayerSubsidy(CharPtr & pChr)
// {
	// // 判断是否有领救济资格
	// if (pChr.isNull())
		// return false;
	// if (IS_CREATURE_FLAG(pChr, en_CreatureFlag_NotSubsidy))
		// return false;
	// // 等级限制
	// uint32 needlv = sXmlDataMgr.GetConfXMLValue("SUBSIDY_LV");
	// if (needlv && pChr->getUInt32Field("lv") >= needlv)
		// return false;
	// // 当前金额
	// uint32 currcoins = GetItemNum(pChr, en_ItemModelId_Coins);
	// uint32 sill = sXmlDataMgr.GetConfXMLValue("SILL_COINS");	// 触底金额	
	// if (currcoins > sill)
		// return false;
	
	// UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	// if (pUser.isNull())
		// return false;
	// // 取银行数据
	// GameBank bank;
	// if (!sBankMgr.GetRealBank(pUser, bank))
		// return false;
	// if (bank.coins + currcoins > sill)
	// {// 发送系统消息
		// char str[512] = "";
		// sprintf(str, GetMsgData("SUBSIDY_MSG2", pUser).c_str(), bank.coins);
		// SendSystemMessage(pChr, str, GetMsgType("SUBSIDY_MSG2", pUser));		
		// return false;
	// }
		
	// uint32 subsidynum = sXmlDataMgr.GetConfXMLValue("SUBSIDY_NUM");// 补助次数	
	// uint32 addcoins = sXmlDataMgr.GetConfXMLValue("SUBSIDY_COINS");// 补助金额
	// time_t nowtime = time(0);
	// if (!sTools.IsSameDate((time_t)bank.data8, nowtime))
	// {
		// bank.data7 = 0;
		// bank.data8 = nowtime;
	// }
	// // 当日补助已经用完
	// if ((uint32)bank.data7 >= subsidynum)
	// {
		// ADD_CREATURE_FLAG(pChr, en_CreatureFlag_NotSubsidy);
		// // 提醒充值
		// WorldPacket packet;
		// if (sProtocolsMgr.CreateTellToDoPacket(&packet, en_RemindType_BuyCoins))
			// SendProtocolsToChr(pChr, &packet);
		// return false;
	// }
	// // 达到补助标准,补钱
	// addItemNum(pChr, en_ItemModelId_Coins, addcoins);	
	// sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_GiftBag, ItemModel_Coins, en_UNT_Add, addcoins, en_GiftType_Subsidy);
	// bank.data7 ++;
	// bank.data8 = nowtime;
	// // 发送系统消息
	// char str[512] = "";
	// sprintf(str, GetMsgData("SUBSIDY_MSG1", pUser).c_str(), addcoins, subsidynum - bank.data7);
	// SendSystemMessage(pChr, str, GetMsgType("SUBSIDY_MSG1", pUser));
	
	// return CenterDatabase.WaitExecute("update game_bank set `data7`=%u, `data8`=%u where bank_id = %u", 
								 // bank.data7, bank.data8, bank.bank_id);
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::NoticeWelfare(CharPtr & pChr)
// {	
	// if (pChr.isNull())
		// return false;
	// WSSocketPtr pSocket = pChr->getSocket();
	// if (pSocket.isNull())
		// return false;
	// std::list<VIPCard> lstWelfare;
	// if (!sVipCardMgr.GetSelfWelfareList(pChr, lstWelfare))
		// return false;
	// WorldPacket newP;
	// std::list<VIPCard>::iterator iter, enditer = lstWelfare.end();
	// for (iter = lstWelfare.begin(); iter != enditer; ++ iter)
	// {
		// uint32 nCoins = (*iter).lgAdd;
		// uint32 endTime = 0;
		// if (pChr->user_data.Get<uint32>((*iter).key, endTime))
		// {
			// if (sProtocolsMgr.CreateUserGainPacket(&newP, en_GiftType_Welfare, nCoins, endTime))
				// pSocket->SendPacket(&newP);
		// }
	// }
	
	// return true;
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::GainWelfare(CharPtr & pChr)
// {
	// if (!IS_CREATURE_FLAG(pChr, en_CreatureFlag_Welfare1))
		// return false;
	
	// std::list<VIPCard> lstWelfare;
	// uint32 allCoins = sVipCardMgr.GetSelfWelfareList(pChr, lstWelfare);
	// if (allCoins)
	// {
		// CANCEL_CREATURE_FLAG(pChr, en_CreatureFlag_Welfare1);
		// addItemNum(pChr, ItemModel_Coins, allCoins);
		// UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
		// if (pUser.isNull())
			// return false;
		// char str[512] = "";
		// sprintf(str, GetMsgData("WELFARE_MSG", pUser).c_str(), allCoins);
		// SendSystemMessage(pChr, str, GetMsgType("WELFARE_MSG", pUser));
		// sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_GiftBag, ItemModel_Coins, en_UNT_Add, allCoins, en_GiftType_Welfare);
		// return true;
	// }
	// return false;
// }
// // 增加幸运卡经验值
// void PublicLogic::AddLuckyCardExps(CharPtr & pChr,const uint32 & model_id,uint32 & num)
// {
	// if(pChr.isNull())
		// return ;
	
	// PGCreatureInterface * pChrAiInfe = TO_CREATURE_INTERFACE(pChr->getAIInterface());
	// if(!pChrAiInfe)
		// return ;
	
	// uint32 curExps = 0;
	// uint32 exps_org = pChrAiInfe->GetXMLData("LUCKY_EXPS");
	// uint8 lv = sVipCardMgr.GetCurrentLuckyLevel(exps_org,curExps);
	// if(lv >= sVipCardMgr.GetLuckyExpMaxLevel())	//超过最大经验值
		// return ;
	
	// uint32 curr_exps = pChrAiInfe->GetXMLData("LUCKY_CURR_EXPS");
	// curr_exps += num;
	
	// bool bSave = false;
	// uint32 lucky_changePer = sXmlDataMgr.GetConfXMLValue("SMALLLUCKY_CHANGE_EXPS");
	// if(model_id == ItemModel_Luck3)
		// lucky_changePer = sXmlDataMgr.GetConfXMLValue("SUPERLUCKY_CHANGE_EXPS");
	// else if(model_id == ItemModel_Luck2)
		// lucky_changePer = sXmlDataMgr.GetConfXMLValue("BIGLUCKY_CHANGE_EXPS");
	
	// if(curr_exps >= lucky_changePer)
	// {
		// exps_org += (curr_exps / lucky_changePer);
		// curr_exps %= lucky_changePer;
		// bSave = true;
	// }
	
	// pChrAiInfe->SetXMLData("LUCKY_EXPS",exps_org);
	// pChrAiInfe->SetXMLData("LUCKY_CURR_EXPS",curr_exps);
	
	// if(bSave)
		// pChr->SaveDB();
	
	// WorldPacket packet;
	// if(sVipCardMgr.CreateUpdateVipDataPacket(&packet,pChr))
		// SendProtocolsToChr(pChr,&packet);
	
	// Log.Notice("AddLuckyCardExps","pChr[%s] lv[%u] curr_exps[%u]",pChr->getCharName().c_str(),exps_org,curr_exps);
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::GainSubsidyCard(CharPtr & pChr)
// {	
	// if (pChr.isNull())
		// return false;
	// UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
	// if (pUser.isNull())
		// return false;
	// ItemModelPtr pModel = sItemModelMgr.load(ItemModel_Subsidy);
	// if (pModel.isNull())
		// return false;
	// uint32 valve = pModel->getUInt32Field("maxhp");
	// uint32 allCoins = GetAllNum(pChr, ItemModel_Coins);
	// if (allCoins > valve)
	// {
		// SendSystemMessage(pChr, GetMsgData("subsidy_error", pUser).c_str(), GetMsgType("subsidy_error", pUser));
		// return false;	
	// }
	// if (!reduceItemNum(pChr, ItemModel_Subsidy, 1))
		// return false;
	// sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_GiftBag, ItemModel_Subsidy, en_UNT_Reduce, 1, en_GiftType_Subsidy1);
	// uint32 addCoins = pModel->getUInt32Field("max_num");
	// addItemNum(pChr, ItemModel_Coins, addCoins);
	// sLogDataMgr.UpdateItemsInfoLog(pChr, en_ST_GiftBag, ItemModel_Coins, en_UNT_Add, addCoins, en_GiftType_Subsidy1);
	// char pStr[512] = "";
	// sprintf(pStr, GetMsgData("subsidy_card", pUser).c_str(), addCoins, GetItemNum(pChr, ItemModel_Subsidy));	
	// SendSystemMessage(pChr, pStr, GetMsgType("subsidy_card", pUser));
	// WorldPacket packet;
	// if (sProtocolsMgr.CreateUserGainPacket(&packet, en_GiftType_Subsidy1, addCoins))
		// SendProtocolsToChr(pChr,&packet);
	// return true;
// }
// //-----------------------------------------------------------------------
// bool PublicLogic::CreateLECards(std::list<GameExchange> * cards,const uint32 & pid,const uint32 & cardsNum,const uint32 & cardsType,const uint32 & days)
// {
	// if(!cardsNum || !days)
		// return false;
	
	// cards->clear();
	
	// char cType = 'G';	//卡类型
	// if(cardsType == 2)
	// {
		// cType = 'S';
	// }
	// else if(cardsType == 3)
	// {
		// cType = 'C';
	// }
	
	// uint32 now_time = time(0);
	// time_t over_time = now_time + days * 86400;
	// over_time = sTools.FormatDataCeil(over_time);
	// String strYMD = "";
	
	// tm overTm = *localtime(&over_time);	//结束时间
	// strYMD = strYMD + ((overTm.tm_year % 100) >= 10 ? StringConverter::toString(overTm.tm_year % 100) : "0" + StringConverter::toString(overTm.tm_year % 100));
	// strYMD = strYMD + ((overTm.tm_mon % 100) >= 9 ? StringConverter::toString(overTm.tm_mon % 100 + 1) : "0" + StringConverter::toString(overTm.tm_mon % 100 + 1));
	// strYMD = strYMD + ((overTm.tm_mday % 100) >= 10 ? StringConverter::toString(overTm.tm_mday % 100) : "0" + StringConverter::toString(overTm.tm_mday % 100));
	
	// CMD5 md5;
	// String strPid = StringConverter::toString(pid);
	// String szPid = md5.GenerateMD5(strPid.c_str());
	// String fkgame = "RRGAME";
	
	// uint32 realover_time = mktime(&overTm);
	// for(uint8 i=0; i<cardsNum; ++i)
	// {
		// GameExchange * pEx = sItemMgr.newDumyExchange();
		// if(!pEx)
			// continue;
		
		// pEx->status = enExchangeStataus_Process;
		// pEx->group_id = 1;
		// pEx->source = pid;	//生成与那个PID
		// pEx->create_time = sTools.GetCurDateTime(now_time);	//创建时间
		// pEx->end_time = sTools.GetCurDateTime(realover_time);	//到期时间
		
		// pEx->data1 = now_time;	//创建时间
		// pEx->data2 = realover_time;	//到期时间
		// pEx->item_model1 = cardsType;	//类型
		// pEx->item_id1 = 80 + (3 - cardsType) * 5;	//折扣率
		
		// uint32 uint_key = now_time;
		// uint_key ^= 0xC3;
		// String transKey = StringConverter::toString(uint_key) + StringConverter::toString(i) + StringConverter::toString(pid) + StringConverter::toString(cardsType);
		// String token = szPid + transKey + fkgame;
		// String md5Str = md5.GenerateMD5(token.c_str());	
		
		// String str1 = md5Str.substr(0,4);
		// String str2 = md5Str.substr(4,4);
		// String str3 = md5Str.substr(8,4);
		// String str4 = md5Str.substr(12,4);
		
		// char buf[256] = "";
		// sprintf(buf,"%c-%s-%s-%s-%s-%s",cType,strYMD.c_str(),str1.c_str(),str2.c_str(),str3.c_str(),str4.c_str());
		
		// pEx->token = buf;
		// pEx->exchange_id = sItemMgr.createExchangeDB(pEx);
		// sBankMgr.LeMaOpLog(pid,en_LMOM_Create,pEx->exchange_id);
		// cards->push_back(*pEx);
		// sItemMgr.freeDumyExchange(pEx);
	// }
	
	// return true;
// }
// //-----------------------------------------------------------------------
// void PublicLogic::CheckTimeOverLeCards(const uint32 & pid)
// {
	// if(!pid)
		// return ;
	
	// uint32 now_time = time(0);
	// uint32 count = sItemMgr.getExchangeDBCount("(source = %u and (status = %u or status = %u) )",
													// pid,enExchangeStataus_Process,enExchangeStataus_YanZheng);
	// if(!count)
		// return ;
	
	// std::list<GameExchange> exchanges;
	// if(!sItemMgr.getExchangeListDB(&exchanges,0,count,"(source = %u and (status = %u or status = %u) )",
												// pid,enExchangeStataus_Process,enExchangeStataus_YanZheng))
		// return ;
	
	// if(exchanges.empty())
		// return ;
	
	// std::list<GameExchange>::iterator iter,ei = exchanges.end();
	// for(iter = exchanges.begin(); iter!=ei; ++iter)
	// {
		// if((*iter).data2 > now_time)	//还未过期
			// continue;
		// sBankMgr.LeMaOpLog(pid,en_LMOM_TimeOver,(*iter).exchange_id);
		// (*iter).status = enExchangeStataus_TimeOver;
		// sItemMgr.updateExchangeDB(&(*iter));
	// }
// }
// //-----------------------------------------------------------------------
// void PublicLogic::LewdLockedMessage(UserPtr &pUser, const uint32 leftTime)
// {
	// if (pUser.isNull())
		// return;
	// WSSocketPtr socket = pUser->m_Socket.getResourcePtr();
	// if (socket.isNull())
		// return;
	// char buf[256];
	// memset(buf, 0, sizeof(buf));
	// sprintf(buf, sMsg.getMessage("lewdlocked").c_str(), leftTime);
	// WorldPacket packet;
	// if (sProtocolsMgr.CreateLocalMessagePacket(&packet, buf, sMsg.getType("lewdlocked")))
		// socket->SendPacket(&packet);
// }
